package com.inforim.c10;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.security.auth.login.LoginException;
import javax.xml.rpc.ServiceException;

import org.apache.axis.client.Stub;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.cognos.developer.schemas.bibus._3.AgentService_PortType;
import com.cognos.developer.schemas.bibus._3.AgentService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.BaseClass;
import com.cognos.developer.schemas.bibus._3.BatchReportService_PortType;
import com.cognos.developer.schemas.bibus._3.BatchReportService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.BiBusHeader;
import com.cognos.developer.schemas.bibus._3.CAM;
import com.cognos.developer.schemas.bibus._3.CAMPassport;
import com.cognos.developer.schemas.bibus._3.ContentManagerServiceStub;
import com.cognos.developer.schemas.bibus._3.ContentManagerService_PortType;
import com.cognos.developer.schemas.bibus._3.ContentManagerService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.DataIntegrationService_PortType;
import com.cognos.developer.schemas.bibus._3.DataIntegrationService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.DeliveryService_PortType;
import com.cognos.developer.schemas.bibus._3.DeliveryService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.Dispatcher_PortType;
import com.cognos.developer.schemas.bibus._3.Dispatcher_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.DisplayObject;
import com.cognos.developer.schemas.bibus._3.EventManagementService_PortType;
import com.cognos.developer.schemas.bibus._3.EventManagementService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.FormFieldVar;
import com.cognos.developer.schemas.bibus._3.FormatEnum;
import com.cognos.developer.schemas.bibus._3.HdrSession;
import com.cognos.developer.schemas.bibus._3.JobService_PortType;
import com.cognos.developer.schemas.bibus._3.JobService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.MonitorService_PortType;
import com.cognos.developer.schemas.bibus._3.MonitorService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.OrderEnum;
import com.cognos.developer.schemas.bibus._3.PromptOption;
import com.cognos.developer.schemas.bibus._3.PropEnum;
import com.cognos.developer.schemas.bibus._3.QueryOptions;
import com.cognos.developer.schemas.bibus._3.ReportService_PortType;
import com.cognos.developer.schemas.bibus._3.ReportService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.SearchPathMultipleObject;
import com.cognos.developer.schemas.bibus._3.SearchPathSingleObject;
import com.cognos.developer.schemas.bibus._3.Sort;
import com.cognos.developer.schemas.bibus._3.SystemService_PortType;
import com.cognos.developer.schemas.bibus._3.SystemService_ServiceLocator;
import com.cognos.developer.schemas.bibus._3.XmlEncodedXML;
import com.inforim.cognos.BaseCognosClient;
import com.inforim.cognos.utils.BIBusHeaderHelper;
import com.inforim.cognos.utils.CognosHelper;

public class CognosClientImpl extends BaseCognosClient {

	static Log log = LogFactory.getLog(CognosClientImpl.class);

	final static int RETRY_MAX_TIMES = 3;

	final static boolean RECONNECT_VALIDATE = true;

	final static String BIBUS_NS = "http://developer.cognos.com/schemas/bibus/3/";

	// Locators
	private AgentService_ServiceLocator agentServiceLocator = null;
	private BatchReportService_ServiceLocator batchRepServiceLocator = null;
	private ContentManagerService_ServiceLocator cmServiceLocator = null;
	private DataIntegrationService_ServiceLocator dataIntServiceLocator = null;
	private DeliveryService_ServiceLocator deliveryServiceLocator = null;
	private EventManagementService_ServiceLocator eventMgmtServiceLocator = null;
	private JobService_ServiceLocator jobServiceLocator = null;
	private MonitorService_ServiceLocator monitorServiceLocator = null;
	private ReportService_ServiceLocator reportServiceLocator = null;
	private SystemService_ServiceLocator systemServiceLocator = null;
	private Dispatcher_ServiceLocator dispatcherServiceLocator = null;
	// Ports
	private AgentService_PortType agentService = null;
	private BatchReportService_PortType batchRepService = null;
	private ContentManagerService_PortType cmService = null;
	private DataIntegrationService_PortType dataIntService = null;
	private DeliveryService_PortType deliveryService = null;
	private EventManagementService_PortType eventMgmtService = null;
	private JobService_PortType jobService = null;
	private MonitorService_PortType monitorService = null;
	private ReportService_PortType repService = null;
	private SystemService_PortType sysService = null;
	private Dispatcher_PortType dispatchService = null;
	private Object[] allServices = new Object[0];
	
	public BiBusHeader getBiBus() {
		if(null != this.cmService) {
			return getBiBusHeader((Stub)this.cmService);
		}
		return null;
	}

	protected BiBusHeader getBiBusHeader(Stub service) {
		BiBusHeader bibus = null;
		bibus = BIBusHeaderHelper.getHeaderObject((service).getResponseHeader(
				BIBUS_NS, "biBusHeader"));
		return bibus;
	}

	protected BiBusHeader getBiBusHeader(Stub service,
			boolean isNewConversation, String RSGroup) {
		BiBusHeader bibus = null;
		bibus = BIBusHeaderHelper.getHeaderObject(
				(service).getResponseHeader(BIBUS_NS, "biBusHeader"),
				isNewConversation, RSGroup);
		return bibus;
	}

	protected Stub getStub(Stub stub) {
		// TODO
		return stub;
	}

	protected Stub getStub(Stub service, boolean isNewConversation,
			String RSGroup) {
		// BiBusHeader bibus = this.getBiBusHeader(service);
		BiBusHeader bibus = null;
		if (null == RSGroup) {
			RSGroup = "";
		}
		bibus = BIBusHeaderHelper.getHeaderObject(
				service.getResponseHeader(BIBUS_NS, "biBusHeader"), isNewConversation,
				RSGroup);

		if (service instanceof ContentManagerService_PortType
				|| service instanceof ContentManagerServiceStub) {
			if (null != bibus) {
				(service).clearHeaders();
				(service).setHeader(BIBUS_NS, "biBusHeader", bibus);
			}
		} else {
			if (bibus == null) {
				BiBusHeader CMbibus = null;
				CMbibus = BIBusHeaderHelper.getHeaderObject(((Stub) cmService)
						.getResponseHeader(BIBUS_NS, "biBusHeader"), true,
						RSGroup);
				(service).clearHeaders();
				(service).setHeader(BIBUS_NS, "biBusHeader", CMbibus);

			} else {
				(service).clearHeaders();
				(service).setHeader(BIBUS_NS, "biBusHeader", bibus);
			}
		}
		return service;
	}

	protected ContentManagerService_PortType connect() {
		BiBusHeader bibus = null;
		int RETRY_MAX_TIMES = CognosClientImpl.RETRY_MAX_TIMES;
		int retry_times = 0;
		while (bibus == null) {
			retry_times++;
			if (RETRY_MAX_TIMES > 0 && retry_times > RETRY_MAX_TIMES) {
				log.error("Try connect failed with max " + RETRY_MAX_TIMES
						+ " times.");
				break;
			}
			// reset();
			agentServiceLocator = new AgentService_ServiceLocator();
			batchRepServiceLocator = new BatchReportService_ServiceLocator();
			cmServiceLocator = new ContentManagerService_ServiceLocator();
			dataIntServiceLocator = new DataIntegrationService_ServiceLocator();
			deliveryServiceLocator = new DeliveryService_ServiceLocator();
			eventMgmtServiceLocator = new EventManagementService_ServiceLocator();
			jobServiceLocator = new JobService_ServiceLocator();
			monitorServiceLocator = new MonitorService_ServiceLocator();
			reportServiceLocator = new ReportService_ServiceLocator();
			systemServiceLocator = new SystemService_ServiceLocator();
			dispatcherServiceLocator = new Dispatcher_ServiceLocator();

			try {
				this.resetDispatch(this.getDispatch());
			} catch (MalformedURLException ex) {
				log.error("Malformed URL: " + ex.getMessage());
				return null;
			} catch (ServiceException ex) {
				log.error("Service Exception: " + ex.getMessage());
				return null;
			}

			try {
				this.testAnonymous();
			} catch (IOException ioex) {
				log.error("Unable to connect: " + this.getDispatch());
				return null;
			}

			SOAPHeaderElement soap = ((Stub) cmService).getResponseHeader(
					BIBUS_NS, "biBusHeader");
			bibus = BIBusHeaderHelper.getHeaderObject(soap, true, "");
			if (bibus != null) {
				((Stub) cmService).setHeader(BIBUS_NS, "biBusHeader", bibus);
				return cmService;
			}

			log.warn("Connect failed. Try again.");
		}
		return null;
	}

	public void reconnect(String passport) throws LoginException {
		this.setPassport(null);
		try {
			ContentManagerService_PortType cmService = this.connect();
			Stub stub = (Stub) cmService;
			if (null != cmService) {
				this.setPassport(null);
				for (BiBusHeader bibus = null; bibus == null;) {
					bibus = new BiBusHeader();
					// bibus = this.getBiBusHeader(stub, false, "");
					CAM cam = new CAM();
					CAMPassport camPass = new CAMPassport();
					camPass.setId(passport);
					cam.setCAMPassport(camPass);
					bibus.setCAM(cam);
					stub.setHeader(BIBUS_NS, "biBusHeader", bibus);
					if (bibus != null) {
						break;
					}
				}
				if (RECONNECT_VALIDATE) {
					if (!testAccount()) {
						throw new LoginException(
								"Logon failed, Passport expired: " + passport);
					}
				}
				this.setPassport(passport);
			}
		} catch (LoginException ex) {
			throw ex;
		} catch (Exception ex) {
			throw new LoginException("Logon failed, "
					+ CognosHelper.parseErrorDetails(ex) + ", Passport: "
					+ passport);
		}
	}

	protected void _logon() throws LoginException {
		this._logon(0);
	}

	protected void _logon(int index) throws LoginException {
		this.setPassport(null);
		this.connect();
		if (null == this.getNamespace()) {
			String[] namespaces = this.getNamespaces();
			if (null != namespaces) {
				log.debug("Logon namespace: " + namespaces[index]);
				this.setNamespace(namespaces[index]);
			}
		}
		if(this.getUsername()!=null&&!this.getUsername().equals("")){
			this._logon(this.getUsername(), this.getPassword(), this.getNamespace());
		}
		
	}

	protected void _logon(String username, String password, String namespace)
			throws LoginException {
		StringBuffer credentialXML = new StringBuffer();
		credentialXML.append("<credential>");
		credentialXML.append("<namespace>");
		credentialXML.append(namespace);
		credentialXML.append("</namespace>");
		credentialXML.append("<username>");
		credentialXML.append(username);
		credentialXML.append("</username>");
		credentialXML.append("<password>");
		credentialXML.append(password);
		credentialXML.append("</password>");
		credentialXML.append("</credential>");
		String encodedCredentials = credentialXML.toString();

		try {
			cmService.logon(new XmlEncodedXML(encodedCredentials),
					new SearchPathSingleObject[] {});
			// may get error of: CAF_VALIDATION_FAILURE
//			SOAPHeaderElement soap = ((Stub) cmService).getResponseHeader(
//					BIBUS_NS, "biBusHeader");
//			((Stub) cmService).setHeader(soap);
						
			getService("ContentManager",false,"");
			if (this.testAccount()) {
				String passport = this._getPassport();
				this.setPassport(passport);
			}
		} catch (java.rmi.RemoteException ex) {
			throw new LoginException("Logon failed, ErrorDetails: "
					+ CognosHelper.parseErrorDetails(ex) + ", Username: "
					+ username + ", Namespace: " + namespace);
		} catch (java.io.IOException ex) {
			throw new LoginException("Logon failed by IOException, Username: "
					+ username + ", Namespace: " + namespace);
		}
	}

	protected void _logoff() {
		try {
//			cmService.logoff();
//			cmService=((ContentManagerServiceStub)getService("ContentManager", true, ""));
//			System.out.println(this._getPassport());
			cmService.logoff();
		} catch (java.rmi.RemoteException ex) {
			log.error("Logoff failed: " + ex.getMessage(), ex);
		}
	}

	protected String _getPassport() {
		String passport = null;
		try {
			BiBusHeader bibus = this.getBiBusHeader((Stub) cmService);
			if (null != bibus.getCAM().getCAMPassport()) {
				passport = bibus.getCAM().getCAMPassport().getId().toString();
			}
		} catch (Exception ex) {
			log.error("Cannot get passport", ex);
		}
		return passport;
	}

	protected String[] getNamespaces() {

		String[] namespaces = new String[] {};

		try {
			DisplayObject[] dob = getBiBusHeader((Stub) cmService).getCAM()
					.getException().getPromptInfo().getDisplayObjects();

			for (int i = 0; i < dob.length; i++) {
				if (dob[i].getName().equalsIgnoreCase("CAMNamespace")) {
					PromptOption[] pop = dob[i].getPromptOptions();
					if (pop != null) {
						namespaces = new String[pop.length * 2];
						for (int j = 0, k = 0; k < pop.length; j++, k++) {
							namespaces[j] = pop[k].getValue();
							namespaces[++j] = pop[k].getId();
						}
					} else {
						if (dob[i + 1].getName().equalsIgnoreCase(
								("CAMNamespaceDisplayName"))) {
							namespaces = new String[2];
							namespaces[0] = dob[i + 1].getValue();
							namespaces[1] = dob[i].getValue();
						} else {
							namespaces = null;
						}
					}
				}
			}
		} catch (NullPointerException npe) {
			namespaces = null;
		}

		// Clear the header so no information from this call remains.
		((Stub) cmService).clearHeaders();

		return namespaces;
	}

	protected boolean testAnonymous() throws IOException {
		boolean r = false;
		try {
			BaseClass bc[] = cmService.query(new SearchPathMultipleObject("/"),
					new PropEnum[] {}, new Sort[] {}, new QueryOptions());
			if (bc != null) {
				r = true;
			} else {
				r = false;
			}
		} catch (java.rmi.RemoteException remoteEx) {
			log.warn("Authentication is required: " + this.getDispatch());
		} catch (java.lang.NullPointerException nullEx) {
			log.error("Unable to connect: " + this.getDispatch());
			throw new IOException("Unable to connect: " + this.getDispatch());
		}
		return r;
	}

	protected boolean testAccount() throws IOException {
		boolean r = false;
		try {
			BaseClass bc[] = cmService.query(new SearchPathMultipleObject("~"),
					new PropEnum[] { PropEnum.searchPath, PropEnum.defaultName,
							PropEnum.name }, new Sort[] {}, new QueryOptions());
			if (bc != null && bc.length > 0) {
				if (null != bc[0] && null != bc[0].getSearchPath()) {
					this.setCamid(bc[0].getSearchPath().getValue());
					this.setFullname(bc[0].getDefaultName().getValue());
					log.debug("Logon Uid: " + this.getUid());
				}
				r = true;
			} else {
				r = false;
			}
		} catch (java.rmi.RemoteException remoteEx) {
			log.warn("Authentication is required: " + this.getDispatch());
		} catch (java.lang.NullPointerException nullEx) {
			log.error("Unable to connect: " + this.getDispatch());
			throw new IOException("Unable to connect: " + this.getDispatch());
		}
		return r;
	}

	public void logon() throws LoginException {
		if (null == this.getPassport()) {
			this._logon();
		} else {
			String passport = this.getPassport();
			this.reconnect(passport);
		}
		if (null != this.getPassport()) {
			log.info("Logon successful, Passport: " + this.getPassport());
		}
	}

	public void logoff() {
		if (null != this.getPassport()) {
			this._logoff();
			log.info("Logoff successful, Passport: " + this.getPassport());
			this.setPassport(null);
		}
	}

	public Stub getService(String name) {
		try {
			String cName = name;
			if (!name.endsWith("Stub")) {
				cName = name.indexOf("_PortType") > 0 ? name : (name
						.indexOf("Service") > 0 ? name : name + "Service")
						+ "_PortType";
				cName = cName.replaceAll("_PortType", "Stub");
			}
			String cName2 = "." + cName;
			for (int i = 0; i < allServices.length; i++) {
				if (allServices[i].getClass().getName().endsWith(cName2)) {
					return getStub((Stub) allServices[i]);
				}
			}
		} catch (ClassCastException ccex) {
			log.error("Cannot cast service object to stub object: " + name);
		}
		return null;
	}

	public Stub getService(String name, boolean isNewConversation,
			String RSGroup) {
		Stub stub = this.getService(name);
		return this.getStub(stub, isNewConversation, RSGroup);
	}

	public Stub getService(String name, String user, String pass, String ns) {
		Stub stub = this.getService(name);

		BiBusHeader bibus = new BiBusHeader();

		CAM cam = new CAM();

		bibus.setCAM(cam);
		bibus.getCAM().setAction("logonAs");
		bibus.setHdrSession(new HdrSession());
		FormFieldVar ffs[] = new FormFieldVar[3];

		ffs[0] = new FormFieldVar();
		ffs[0].setName("CAMUsername");
		ffs[0].setValue(user);
		ffs[0].setFormat(FormatEnum.not_encrypted);

		ffs[1] = new FormFieldVar();
		ffs[1].setName("CAMPassword");
		ffs[1].setValue(pass);
		ffs[1].setFormat(FormatEnum.not_encrypted);

		ffs[2] = new FormFieldVar();
		ffs[2].setName("CAMNamespace");
		ffs[2].setValue(ns);
		ffs[2].setFormat(FormatEnum.not_encrypted);

		bibus.getHdrSession().setFormFieldVars(ffs);

		stub.setHeader(BIBUS_NS, "biBusHeader", bibus);
		// this.setPassword(password)
		return stub;
	}

	public void resetDispatch(String dispatch) throws MalformedURLException,
			ServiceException {
		java.net.URL endPointURL = new java.net.URL(dispatch);
		agentService = agentServiceLocator.getagentService(endPointURL);
		batchRepService = batchRepServiceLocator
				.getbatchReportService(endPointURL);
		cmService = cmServiceLocator.getcontentManagerService(endPointURL);
		dataIntService = dataIntServiceLocator
				.getdataIntegrationService(endPointURL);
		deliveryService = deliveryServiceLocator
				.getdeliveryService(endPointURL);
		eventMgmtService = eventMgmtServiceLocator
				.geteventManagementService(endPointURL);
		jobService = jobServiceLocator.getjobService(endPointURL);
		monitorService = monitorServiceLocator.getmonitorService(endPointURL);
		repService = reportServiceLocator.getreportService(endPointURL);
		sysService = systemServiceLocator.getsystemService(endPointURL);
		dispatchService = dispatcherServiceLocator.getdispatcher(endPointURL);
		allServices = new Object[] { agentService, batchRepService, cmService,
				dataIntService, deliveryService, eventMgmtService, jobService,
				monitorService, repService, sysService, dispatchService };
		this.setDispatch(dispatch);
	}

	@SuppressWarnings("rawtypes")
	final public List getTree(String path, int deep) {
		// query search sort
		Sort defaultSort = new Sort();
		defaultSort.setPropName(PropEnum.defaultName);
		defaultSort.setOrder(OrderEnum.ascending);
		// Sort classSort = new Sort();
		// classSort.setPropName(PropEnum.objectClass);
		// classSort.setOrder(OrderEnum.ascending);
		// Sort positionSort = new Sort();
		// positionSort.setPropName(PropEnum.position);
		// positionSort.setOrder(OrderEnum.ascending);
		Sort[] sorts = { defaultSort };
		return getTree(path, sorts, deep);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	final public List getTree(String xpath, Sort[] sorts, int deep) {
		List tree = new LinkedList();
		xpath = (null != xpath ? xpath : "~/folder[@name='My Folders']"); // ~/folder[@name='�ҵ��ļ���']
		String xopts = getSearchOpts(xpath);
		// query search props
		PropEnum[] props = { PropEnum.searchPath, PropEnum.defaultName,
				PropEnum.hasChildren, PropEnum.objectClass, PropEnum.format,
				PropEnum.storeID, PropEnum.searchPath, PropEnum.identity,
				PropEnum.defaultDescription, PropEnum.uri, PropEnum.target };
		// query options
		QueryOptions queryOptions = new QueryOptions();
		if (null == sorts) {
			Sort defaultSort = new Sort();
			defaultSort.setPropName(PropEnum.defaultName);
			defaultSort.setOrder(OrderEnum.ascending);
			sorts = new Sort[] { defaultSort };
		}
		BaseClass[] matches = this.search(xpath, SCOPE_ONELEVEL, props, sorts,
				queryOptions, 0, 0, null);
		if (0 == deep)
			deep = 5; // 5 levels deep max
		deep--;
		String gw = "";
		if (null != this.getGateway()) {
			try {
				gw = URLEncoder.encode(this.getGateway(), "UTF-8");
			} catch (UnsupportedEncodingException e) {
				log.debug("gateway missed: " + this.getGateway());
			}
		}
		if (null != matches) {
			for (int a = 0; a < matches.length; a++) {
				BaseClass match = matches[a];
				Map node = new HashMap();
				String name = match.getDefaultName().getValue();
				boolean hasChildren = match.getHasChildren().isValue();
				String clazz = match.getObjectClass().getValue().getValue();
				String path = match.getSearchPath().getValue();
				String url = match.getSearchPath().getValue();
				// String encodedPath = path;
				String encodedPath = path;
				// try {
				// encodedPath = URLEncoder.encode(path, "UTF-8");
				// } catch (UnsupportedEncodingException e) {
				// encodedPath = url;
				// }
				String href = url;
				String guid = match.getStoreID().getValue().get_value();
				try {
					encodedPath = URLEncoder.encode(path, "utf-8");
				} catch (UnsupportedEncodingException ex) {
					log.warn("encoding uri failed.");
				}
				if ("report".equalsIgnoreCase(clazz)) {
					href = "?b_action=cognosViewer&ui.action=run&ui.object="
							+ encodedPath + "&ui.name=" + name
							+ "&run.outputFormat=&run.prompt=true";
					/*
					 * href = "?b_action=cognosViewer&ui.action=run&ui.object="
					 * + encodedPath + "&ui.name=" + name +
					 * "&run.outputFormat=&run.prompt=true&ui.gateway=" + gw;
					 */
				} else if ("query".equalsIgnoreCase(clazz)) {
					href = "?b_action=xts.run&m=portal/launch.xts&ui.tool=QueryStudio&ui.action=edit&ui.object="
							+ encodedPath
							+ "&ui.drillThroughTargetParameterValues=";
					/*
					 * href =
					 * "?b_action=xts.run&m=portal/launch.xts&ui.tool=QueryStudio&ui.action=edit&ui.object="
					 * + encodedPath +
					 * "&ui.drillThroughTargetParameterValues=&ui.gateway=" +
					 * gw;
					 */
				} else if ("analysis".equalsIgnoreCase(clazz)) {
					// href =
					// "?b_action=xts.run&m=portal/launch.xts&ui.tool=AnalysisStudio&ui.action=edit&ui.object="
					// + encodedPath
					// +
					// "&encoding=UTF-8&launch.openJSStudioInFrame=true&ui.drillThroughTargetParameterValues="
					// ;
					// if (null != ConfigUtils.props
					// .getProperty("c8.analysis.edit")) {
					if (null != System.getProperty("c8.analysis.edit")) {

						href = "?b_action=xts.run&m=portal/launch.xts&ui.gateway="
								// + "%2Fp2pd%2Fservlet%2Fdispatch"
								+ gw
								+ "&ui.tool=AnalysisStudio&ui.object="
								+ encodedPath
								+ "&ui.drillThroughTargetParameterValues=&ui.action=edit&launch.openJSStudioInFrame=true";
					} else {
						href = "?b_action=cognosViewer&ui.action=run&ui.object="
								+ encodedPath
								+ "&ui.name="
								+ name
								+ "&run.outputFormat=&run.prompt=true";
					}
				} else if ("dashboard".equalsIgnoreCase(clazz)) {
					href = "?b_action=dashboard&pathinfo=/cm&frag-header=true&path=storeID(%22"
							+ guid + "%22)";
				} else if ("pagelet".equalsIgnoreCase(clazz)) {
					href = "?b_action=dashboard&pathinfo=/cm&frag-header=true&path=storeID(%22"
							+ guid + "%22)";
				} else if ("URL".equals(clazz)) {
					href = ((com.cognos.developer.schemas.bibus._3.URL) match)
							.getUri().getValue();
				} else if ("shortcut".equals(clazz)) {
					// com.cognos.developer.schemas.bibus._3.Shortcut s =
					// ((com.cognos.developer.schemas.bibus._3.Shortcut) match);
					// BaseClassArrayProp target = s.getTarget();
					// log.info("target: " + target);
					// BaseClass[] targetArray = target.getValue();
					// for (BaseClass tbc : targetArray) {
					// log.info("tbc: " + tbc);
					// }
					// com.cognos.developer.schemas.bibus._3.Shortcut s =
					// ((com.cognos.developer.schemas.bibus._3.Shortcut) match);
					// // href = s.getTarget().toString();
					href = "";
					// // for(Object b : s.getDescription().getValue()) {
					// // log.info("s:" + b);
					// // }
					// s.
					// href =
					// s.getDescription().getValue().length + "";
				} else {
					href = "?b_action=cognosViewer&ui.action=run&ui.object="
							+ encodedPath
							+ "&ui.name=TODO&run.outputFormat=&run.prompt=true";
				}
				boolean leaf = !("folder".equals(clazz) || "package"
						.equals(clazz));
				((Map) node).put("name", name);
				((Map) node).put("hasChildren", new Boolean(hasChildren));
				((Map) node).put("clazz", clazz);
				((Map) node).put("path", path);
				((Map) node).put("leaf", new Boolean(leaf));
				((Map) node).put("url", url);
				((Map) node).put("href", href);
				// node.put("id", parseQueryPath(xpath) + "/" + name);
				node.put("id", parseQueryPath(path));
				node.put("guid", guid);
				if (!leaf && hasChildren) {
					if (deep > 0) {
						String sub_xpath = path + "/*" + xopts;
						node.put("children",
								this.getTree(sub_xpath, sorts, deep));
					}
				}
				tree.add(node);
			}
		}
		return tree;
	}

	final public String[][] getData(String path, int scope, Sort[] sorts,
			long skip, long size) {
		String[][] data = null;
		path = (null != path ? path : "~/folder[@name='My Folders']"); // ~/folder[@name='�ҵ��ļ���']
		BaseClass[] matches = this.search(path, scope, null, sorts, null, skip,
				size, null);
		if (null != matches) {
			data = new String[matches.length][7];
			int i = 0;
			for (int a = 0; a < matches.length; a++) {
				BaseClass match = matches[a];
				String clazz = match.getObjectClass().getValue().getValue();
				String guid = match.getStoreID().getValue().get_value();
				String name = match.getDefaultName().getValue();
				String spath = match.getSearchPath().getValue();
				String url = match.getSearchPath().getValue();
				// String id = parseQueryPath(path) + "/" + name;
				String id = parseQueryPath(spath);
				String ePath = "";
				try {
					ePath = URLEncoder.encode(spath, "utf-8");
				} catch (UnsupportedEncodingException ex) {
					log.warn("encoding uri failed.");
				}
				data[i] = new String[] { guid, id, name, clazz, spath, ePath,
						url };
				i++;
			}
		} else {
			data = new String[0][7];
		}
		return data;
	}

	final public String[][] getData(String path, long skip, long size) {
		Sort sort = new Sort();
		sort.setPropName(PropEnum.defaultName);
		sort.setOrder(OrderEnum.ascending);
		Sort[] sorts = { sort };
		return getData(path, SCOPE_ONELEVEL, sorts, skip, size);
	}

	final public String getSearchOpts(String path) {
		String rPerm = "";
		if (path.matches("^(.*)\\/\\*\\[(.*)\\]$")) {
			rPerm = path.substring(path.lastIndexOf("/*") + "/*".length());
		}
		return rPerm;
	}

	final public String parseQueryPath(String xpath) {
		// TODO jhsea3do, e.g. ~op_guanghui
		String spath = xpath.replaceAll("^CAMID\\(.*\\)", "~");
		StringBuffer sb = new StringBuffer();
		String[] nodes = spath.split("/");
		String regex = "^(folder|report|package|URL)\\[\\@name=\\'(.*)\\'\\]";
		for (int i = 0; i < nodes.length; i++) {
			String node = nodes[i];
			String clazz = null;
			String name = null;
			if (node.matches(regex)) {
				java.util.regex.Pattern p = java.util.regex.Pattern
						.compile(regex);
				java.util.regex.Matcher m = p.matcher(node);
				if (m.matches()) {
					clazz = m.group(1);
					name = m.group(2);
					if (!"folder".equals(clazz)) {
						node = clazz + ":" + name;
					} else {
						node = name;
					}
				}
			}
			sb.append(node);
			sb.append("/");
		}
		if (!spath.endsWith("/")) {
			sb.delete((sb.length() - 1), sb.length());
		}
		return sb.toString();
	}

	final public String formatQueryPath(String desc) {
		String[] nodes = desc.split("/");
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < nodes.length; i++) {
			String regex = "^(folder|report|package|URL)\\:(.*)";
			String node = nodes[i];
			// TODO jhsea3do, 7 top folders
			// if (desc.startsWith("/content") && 1 == i &&
			// "content".equals(node)) {
			if (desc.startsWith("/") && 1 == i) {
				node = nodes[i];
			} else if ("~".equals(node) || "*".equals(node) || "".equals(node)) {
				node = nodes[i];
			} else {
				if (node.indexOf("[") > 0 && node.indexOf("]") > 0) {
					node = nodes[i];
				} else {
					if (!desc.endsWith("/") && i == (nodes.length - 1)
							&& !node.matches(regex)) {
						node = nodes[i];
					} else {
						String name = null;
						String clazz = null;
						if (node.matches(regex)) {
							java.util.regex.Pattern p = java.util.regex.Pattern
									.compile(regex);
							java.util.regex.Matcher m = p.matcher(node);
							if (m.matches()) {
								clazz = m.group(1);
								name = m.group(2);
							}
						} else {
							clazz = "folder";
							name = node;
						}
						node = clazz + "[@name='" + name + "']";
					}
				}
			}
			if (i > 0) {
				sb.append("/");
			}
			sb.append(node);
		}
		return sb.toString();
	}


}
